package arithmetic.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author jiangfeng 2019/8/21 14:44
 *
 * 多线程计算 数组求和.
 */
public class MultiSumOdd implements Callable{

    public static void main(String[] args) {
        // int core = Runtime.getRuntime().availableProcessors();
        MultiSumOdd object = new MultiSumOdd();

        int n = 911216191;
        object.singleSum(n);
        System.out.println("---------------");
        //System.out.println(Runtime.getRuntime().availableProcessors());//4核
        object.mutilSum(n,4);

    }

    int start;
    int end;

    public MultiSumOdd(){
    }

    public MultiSumOdd(int start,int end){
        this.end=end;
        this.start=start;
    }

    public long singleSum(int n) {
        long s = System.currentTimeMillis();
        long result = 0;
        for (int i = 1; i < n + 2; i += 2) {
            result += i;
        }
        System.out.println("用时:"+(System.currentTimeMillis()-s));
        System.out.println("single结果:"+result);
        return result;
    }

    public long mutilSum(int n,int cores){
        long s = System.currentTimeMillis();
        int size = n+1/2;
        int sement = size/cores;// 分的多少段;

        ExecutorService executor = Executors.newFixedThreadPool(cores);
        List<Future<Long>> ans = new ArrayList<>();
        for (int i = 0; i < cores; i++) {
            start = i * sement % 2 == 0 ? i * sement + 1 : i * sement;
            end = sement%2==0?start+sement:sement+start-1;
            Future submit = executor.submit(new MultiSumOdd(start, end));
           /* Future submit = executor.submit(() -> {
                 MultiSumOdd.sum_(start, end);
            });*/
            ans.add(submit);
        }

        long result=0;
        for (int j = 0; j < ans.size(); j++) {
            try {
                result+=ans.get(j).get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        result+=sum_(cores*sement,n+1);
        executor.shutdown();// 不提交则一直阻塞,导致主线程无法关闭
        System.out.println(System.currentTimeMillis()-s);
        System.out.println("结果:"+result);
        return result;
    }


    /**
     * 含头不含尾
     * @param start
     * @param end
     * @return
     */
    public static long sum_(int start,int end){
        long result =0;
        for(int i=start;i<end;i+=2){
            result+=i;
        }
        return result;
    }

    @Override
    public Object call() throws Exception {
        return sum_(start,end);
    }
}
